package de.homer.persistence;

import java.util.Collection;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import de.homer.persistence.utils.HibernateSessionFactory;

/**
 * An abstract repository using JPA. The methods use a hibernate {@link Session}
 * to manage the entity of the generic type
 * 
 * @author André Stannek
 * 
 * @param <T>
 *            the type of entity that is managed by the repository
 */
public abstract class AbstractRepositoryJPA<T> implements Repository<T> {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8457112803659562803L;

	/*
	 * (non-Javadoc)
	 * 
	 * @see de.homer.core.repository.Repository#merge(java.lang.Object)
	 */
	@Override
	public final void merge(final T entity) {
		final Session session = HibernateSessionFactory.getSessionFactory()
				.getCurrentSession();
		final Transaction transaction = session.beginTransaction();
		session.saveOrUpdate(entity);
		transaction.commit();
	}

	/**
	 * Generic get all can be called by subclasses when the actual entity type
	 * is know. There is no generic implementation possible without knowing that
	 * type.
	 * 
	 * @param entityType
	 *            the type of the entities to get
	 * @return all entities known in the system
	 */
	@SuppressWarnings("static-method")
	public final Collection<T> getAll(final Class<T> entityType) {

		final Session session = HibernateSessionFactory.getSessionFactory()
				.getCurrentSession();
		final Transaction transaction = session.beginTransaction();
		final Query query = session.createQuery("from " + entityType.getName());
		@SuppressWarnings("unchecked")
		final List<T> list = query.list();
		transaction.commit();
		return list;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see de.homer.core.repository.Repository#remove(java.lang.Object)
	 */
	@Override
	public final void remove(final T entity) {
		final Session session = HibernateSessionFactory.getSessionFactory()
				.getCurrentSession();
		final Transaction transaction = session.beginTransaction();
		session.delete(entity);
		transaction.commit();
	}
}
